setfenv(1, GraphPaper)

--[[-----------------------------------------------------------------------------
Common for all options
-------------------------------------------------------------------------------]]
local hideIndependent = { [false] = { spacingX = true, spacingY = true }, [true] = { spacing = true, squaring = true } }
local options, optionPanel = { type = 'group', args = { } }

local function Get(info)
	return settings[info[#info]]
end

local function GetColor(info)
	return unpack(settings[info[#info]])
end

local function HideOptions(info)
	return hideIndependent[settings.independent][info[#info]]
end

local function Set(info, value)
	settings[info[#info]] = value
	if info[#info] == "centerThickness" then
		UpdateCenterLines()
		if settings.absolute then return end
	end
	DrawGrid()
end

local color
local function SetColor(info, ...)
	color = settings[info[#info]]
	color[1], color[2], color[3], color[4] = ...
	if info[#info] == "gridColor" then
		ColorGrid()
	else
		UpdateCenterLines()
	end
end

local function SetState(info, value)
	settings[info[#info]] = value
	UpdateState()
end

--[[-----------------------------------------------------------------------------
Base Options
-------------------------------------------------------------------------------]]
local baseOptions = {
	type = 'group',
	name = "Base Options",
	get = Get,
	set = Set,
	args = {
		desc = {
			type = 'description',
			order = 1,
			name = format(L["These options allow you to change the appearance of %s.\n"], title)
		},
		hide = {
			type = 'toggle',
			order = 2,
			name = "Hide",
			desc = L["Remove the grid."],
			set = SetState
		},
		overlay = {
			type = 'toggle',
			order = 3,
			name = L["Overlay"],
			desc = L["Move the grid from the background to the foreground."],
			set = SetState
		},
		centerHeader = {
			type = 'header',
			order = 4,
			name = L["Center Lines"],
		},
		centerColor = {
			type = 'color',
			order = 5,
			name = L["Color"],
			desc = L["Change the color of the center lines."],
			hasAlpha = true,
			get = GetColor,
			set = SetColor
		},
		centerThickness = {
			type = 'range',
			order = 6,
			name = L["Size"],
			desc = L["Change the thickness of the center lines."],
			min = 1, max = 3, step = 1
		},
		gridHeader = {
			type = 'header',
			order = 7,
			name = L["Grid Lines"],
		},
		gridColor = {
			type = 'color',
			order = 8,
			name = L["Color"],
			desc = L["Change the color of the grid lines."],
			hasAlpha = true,
			get = GetColor,
			set = SetColor
		},
		gridThickness = {
			type = 'range',
			order = 9,
			name = L["Size"],
			desc = L["Change the thickness of the grid lines."],
			min = 1, max = 3, step = 1
		},
		spacingHeader = {
			type = 'header',
			order = 10,
			name = L["Line Spacing"],
		},
		absolute = {
			type = 'toggle',
			order = 11,
			name = L["Absolute"],
			desc = L["Grid lines are spaced without regard for line thickness."]
		},
		spacing = {
			type = 'range',
			order = 12,
			name = L["Spacing"],
			desc = L["Adjust the distance between grid lines."],
			hidden = HideOptions,
			min = 8, max = 128, step = 1,
			get = function(info)
				return settings.spacingX
			end,
			set = function(info, value)
				settings.spacingX = value
				DrawGrid()
			end
		},
		spacingX = {
			type = 'range',
			order = 12,
			name = L["Spacing, Horizontal"],
			desc = L["Adjust the distance between grid lines along the X-axis."],
			hidden = HideOptions,
			min = 8, max = 128, step = 1
		},
		independent = {
			type = 'toggle',
			order = 13,
			name = L["Independent"],
			desc = L["Adjust the spacing for grid lines seperately for each axis."],
			set = function(info, value)
				settings[info[#info]] = value
				if value then
					settings.spacingY = settings.spacingX
				end
				DrawGrid()
			end
		},
		spacingY = {
			type = 'range',
			order = 14,
			name = L["Spacing, Vertical"],
			desc = L["Adjust the distance between grid lines along the Y-axis."],
			hidden = HideOptions,
			min = 8, max = 128, step = 1
		},
		squaring = {
			type = 'toggle',
			order = 14,
			name = L["Squaring"],
			desc = L["Make the grid lines intersect to form squares."],
			hidden = HideOptions
		}
	}
}

----------     Helper     ----------

local function RegisterOptions(name, optionsTable)
	local baseOverride = name ~= "Base" or nil
	options.args[name] = optionsTable
	return LibStub("AceConfigDialog-3.0"):AddToBlizOptions(title, baseOverride and name, baseOverride and title, name)
end

--[[-----------------------------------------------------------------------------
Global to addon
-------------------------------------------------------------------------------]]
function OpenConfig()
	if optionPanel:IsVisible() then
		InterfaceOptionsFrame_OpenToCategory(optionPanel.Profiles)
	else
		InterfaceOptionsFrame_OpenToCategory(optionPanel)
	end
end

function SetupConfig()
	LibStub('AceConfigRegistry-3.0'):RegisterOptionsTable(title, options)
	optionPanel = RegisterOptions("Base", baseOptions)
	optionPanel.Profiles = RegisterOptions("Profiles", LibStub('AceDBOptions-3.0'):GetOptionsTable(addon.db))

	local frame = optionPanel:CreateFontString(nil, 'ARTWORK', 'GameFontNormalSmall')
	frame:SetAlpha(0.75)
	frame:SetJustifyH('LEFT')
	frame:SetJustifyV('TOP')
	frame:SetText(L["Version"] .. ": " .. GetAddOnMetadata(title, 'Version'))
	frame:SetPoint('TOPRIGHT', optionPanel, 'TOPRIGHT', -16, -19)

	_G['SLASH_' .. title .. 1] = '/' .. title
	_G['SLASH_' .. title .. 2] = '/' .. strlower(title)
	_G['SLASH_' .. title .. 3] = '/' .. strupper(title)
	_G['SLASH_' .. title .. 4] = "/gpaper"
	_G['SLASH_' .. title .. 5] = "/GPAPER"
	SlashCmdList[title] = function(cmd)
		cmd = strlower(strtrim(cmd))
		local spacing = floor(tonumber(cmd) or 0)
		if spacing >= 8 and spacing <= 128 then
			settings.spacingX, settings.spacingY = spacing, spacing
			DrawGrid()
		elseif cmd == "config" then
			OpenConfig()
		else
			if cmd == "hide" then
				settings.hide = true
			elseif cmd == "show" then
				settings.hide = false
			else
				settings.hide = not settings.hide
			end
			UpdateState()
		end
		UpdateConfig()
	end
end

function UpdateConfig()
	if optionPanel:IsVisible() then
		LibStub('AceConfigRegistry-3.0').callbacks:Fire('ConfigTableChange', title .. '\001Base')
	end
end
